﻿#include "ui/bar.h"
#include "texture.h"
#include "font.h"
#include "draw.h"

#include <iostream>

using namespace std;
using namespace anip;

void ui::RadioBarItem::setText(const wstring& text)
{
	if (_tex != nullptr)
	{
		_tex->finalize();
		delete _tex;
		_tex = nullptr;
	}
	_text = text;
}

Texture2D* ui::RadioBarItem::getTex()
{
	if (_tex == nullptr)
	{
		auto layout = TextRenderer::layoutPixelPerfectString(
			_text, ((RadioBar&)_container).getFont());
		_tex = TextRenderer::renderString(*layout);
		_texSize = layout->drawingSize();
		delete layout;
	}
	return _tex;
}

anip::ui::RadioBarItem::~RadioBarItem()
{
	if (_tex != nullptr)
	{
		_tex->finalize();
		delete _tex;
	}
}

ui::RadioBar::RadioBar(Container* parent, invec2 pos, invec2 size)
{
	if (parent != nullptr) parent->addChild(*this);
	setPosition(pos);
	setSize(size);
}

void ui::RadioBar::processMouseMove(invec2 pos)
{
	int index = (int)(pos.x / _size.x * items.size());
	if (index != _hoveredIndex && index < (int)items.size() && index >= 0)
	{
		if (_hoveredIndex != -1)
		{
			items[_hoveredIndex]._hovered = false;
			items[_hoveredIndex]._pressed = false;
		}
		items[index]._hovered = true;
		_hoveredIndex = index;
		postSignal({ ui::Signal::Type::NeedsRedraw });
	}

	Control::processMouseMove(pos);
}

void ui::RadioBar::processMouseLeave()
{
	if (_hoveredIndex != -1)
	{
		items[_hoveredIndex]._hovered = false;
		items[_hoveredIndex]._pressed = false;
		postSignal({ ui::Signal::Type::NeedsRedraw });
	}
	_hoveredIndex = -1;

	Control::processMouseLeave();
}

void ui::RadioBar::processMouseButton(MouseButton btn, ButtonAction action)
{
	// ANIP_TODO more buttons?
	if (btn == MouseButton::Left && _hoveredIndex != -1)
	{
		auto& it = items[_hoveredIndex];
		postSignal({ ui::Signal::Type::NeedsRedraw });
		if (action == ButtonAction::Down)
		{
			it._pressed = true;
			it.toggle();
			if (it.onClick) it.onClick(it);
		}
		else if (action == ButtonAction::Up)
		{
			it._pressed = false;
		}
	}

	Control::processMouseButton(btn, action);
}

void anip::ui::RadioBar::paint()
{
	// fixme: it should anyway draw when size() == 1
	if (items.size() < 2) return;

	vec2 siz{ _size.x / items.size(), _size.y };
	vec2 sizx{ _size.x / items.size(), 0 };
	color sepcolor = normalColor().mulWithoutAlpha(hoverFactor);

	for (int i = 0; i < (int)items.size(); i++)
	{
		auto& it = items[i];
		color col = it.isSelected() ? selectedColor : normalColor;
		if (it._pressed) col = col.mulWithoutAlpha(pressFactor);
		else if (it._hovered) col = col.mulWithoutAlpha(hoverFactor);

		if (i == 0)
		{
			Draw::roundedRect(_absPos, siz, roundRadius, col);
			Draw::rect(_absPos + sizx * 0.5f, vec2{ siz.x * 0.5f, siz.y }, col);
		}
		else if (i == items.size() - 1)
		{
			vec2 pos = _absPos + vec2{ _size.x - siz.x, 0 };
			Draw::roundedRect(pos, siz, roundRadius, col);
			Draw::rect(pos, vec2{ siz.x * 0.5f, siz.y }, col);
			Draw::rect(pos, { 1, _size.y }, sepcolor);
		}
		else
		{
			Draw::rect(_absPos + sizx * (float)i, siz, col);
			Draw::rect(_absPos + sizx * (float)i, { 2, _size.y }, sepcolor);
		}

		Texture2D* tex = it.getTex();
		if (tex == nullptr) continue;
		vec2 s = it._texSize;
		Draw::text(
			_absPos + sizx * (float)i + siz * 0.5f - s * 0.5f,
			s, *tex, textColor);
	}
}

void anip::ui::RadioBar::flow(Flow& f)
{
	if (layoutOptions.type != layoutOptions.Flow)
	{
		Control::flow(f);
		return;
	}

	if (items.size() < 1) return;

	float textSize = 0;
	for (auto& i : items)
	{
		Texture2D* tex = i.getTex();
		if (tex == nullptr) continue;
		textSize = max(i._texSize.y, textSize);
	}

	if (f.currentX > f.borderRight)
		f.newLine();

	// always extend, regardless of whether stretchX is set
	vec2 tsize = { f.borderRight - f.currentX, textSize + r::Flow_Text_vMargin * 2 };

	setSize({
		max(tsize.x, layoutOptions.minSize.x),
		max(tsize.y, layoutOptions.minSize.y) });

	if (f.currentX + _size.x > f.borderRight)
		f.newLine();
	f.lineHeight = max(f.lineHeight, _size.y);
	setPosition({ f.currentX, f.currentY });
	f.currentX += _size.x + r::Flow_Separator;
}

ui::RadioBarItem& ui::RadioBar::addItem(const wstring& text)
{
	items.push_back(RadioBarItem(*this));
	auto& it = items[items.size() - 1];
	it.setText(text);
	return it;
}

int anip::ui::RadioBar::hoveredIndex() const
{
	return _hoveredIndex;
}